﻿#include "listenthreadx.h"
#include "linkx.h"
template<typename m_>
void listenthreadx::MainFunction()
{
	WSADATA wsaData;
	DWORD Ret;


	if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
		return FALSE;

	//创建Listen socket
	if ((m_slisten = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
		return;

	// Event for handling Network IO
	m_hevent = WSACreateEvent();
	if (m_hevent == WSA_INVALID_EVENT)
	{
		closesocket(m_slisten);
		return;
	}

	// Request async notification
	int nRet = WSAEventSelect(m_slisten, m_hevent, FD_ACCEPT);

	if (nRet == SOCKET_ERROR)
	{
		closesocket(m_slisten);
		return;
	}

	SOCKADDR_IN InternetAddr;
	InternetAddr.sin_family = AF_INET;
	InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	InternetAddr.sin_port = htons(m_sPort);

	if (bind(m_slisten, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
	{
		m_piocpx->m_brunning = false;		//程序需要退出 
		return;
	}

	// Set the socket to listen
	nRet = listen(m_slisten, 25);
	if (nRet == SOCKET_ERROR)
	{
		closesocket(m_slisten);
		m_piocpx->m_brunning = false;		//程序需要退出
		return;
	}

	//Listen
	WSANETWORKEVENTS events;
	while(m_piocpx->m_brunning)
	{

		DWORD dwRet;
		dwRet = WSAWaitForMultipleEvents(1,&m_hevent, FALSE, 10000, FALSE);

		if (dwRet == WSA_WAIT_TIMEOUT)
			continue;

		int nRet = WSAEnumNetworkEvents(m_slisten, m_hevent, &events);

		if (nRet == SOCKET_ERROR)
			break;

		if (events.lNetworkEvents & FD_ACCEPT)
		{
			if (events.iErrorCode[FD_ACCEPT_BIT] == 0)
				onaccept();
			else	
				break;
		}
	}

	//线程就退出了
}
template<typename m_>
void listenthreadx::onaccept()
{
	SOCKADDR_IN	SockAddr;
	SOCKET		clientSocket;
	
	int			nRet;
	int			nLen;

	// accept the new socket descriptor
	nLen = sizeof(SOCKADDR_IN);
	
	clientSocket = WSAAccept(m_slisten, (LPSOCKADDR)&SockAddr,&nLen,NULL,0); 

	if (clientSocket == INVALID_SOCKET )
	{
		nRet = WSAGetLastError();
		if (nRet != WSAEWOULDBLOCK)
			return;
	}


	tcplinkx_<m_>* plink = m_::alloc(tcplinkx_<m_>);

	if(plink ==NULL)
		return;
	
	plink->m_dwSocketID = ++m_socketid;
	plink->m_ssocket = clientSocket;	
	plink->m_dwpeerip = SockAddr.sin_addr.S_un.S_addr;
	plink->m_usport = SockAddr.sin_port;

	if(CreateIoCompletionPort((HANDLE) plink->m_ssocket , m_piocpx->m_hCompletionPort, (DWORD)plink, 0)==0)
	{	
		m_::free(plink);
        closesocket( clientSocket );
        return;
    }

	plink->m_recvobjx.operation = OP_ACCEPT;

	BOOL bSuccess = PostQueuedCompletionStatus(m_piocpx->m_hCompletionPort, -1, (DWORD)plink, &(plink->m_recvobjx.ol));
	
	if ( (!bSuccess ))
	{            
		m_::free(plink);
		closesocket( clientSocket );
        return;
    }	
}